package vip.xiaonuo.vein.task;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import vip.xiaonuo.core.timer.TimerTaskRunner;
import vip.xiaonuo.facedoor.iservice.issulog.DeviceLogService;
import vip.xiaonuo.facedoor.modular.device.entity.DeviceCategory;
import vip.xiaonuo.facedoor.modular.devicebase.entity.DeviceBase;
import vip.xiaonuo.facedoor.modular.devicebase.service.DeviceBaseService;
import vip.xiaonuo.facedoor.modular.memberfeatures.entity.MemberFeatures;
import vip.xiaonuo.facedoor.modular.memberfeatures.service.MemberFeaturesService;
import vip.xiaonuo.facedoor.modular.memberuser.entity.MemberUser;
import vip.xiaonuo.facedoor.modular.memberuser.service.MemberUserService;
import vip.xiaonuo.vein.controller.vo.AddFeatureInfo;
import vip.xiaonuo.vein.controller.vo.UpdateFeatureInfo;
import vip.xiaonuo.vein.model.ReqUtil;
import vip.xiaonuo.vein.modular.veindeviceevent.entity.VeinDeviceEvent;
import vip.xiaonuo.vein.modular.veindeviceevent.enums.VeinDeviceEventPersonTypeEnum;
import vip.xiaonuo.vein.modular.veindeviceevent.enums.VeinDeviceEventStatusEnum;
import vip.xiaonuo.vein.modular.veindeviceevent.enums.VeinDeviceEventSysTypeEnum;
import vip.xiaonuo.vein.modular.veindeviceevent.service.VeinDeviceEventService;
import vip.xiaonuo.vein.modular.veinpalmdeviceuserrelate.entity.VeinPalmDeviceUserRelate;
import vip.xiaonuo.vein.modular.veinpalmdeviceuserrelate.enums.VeinPalmDeviceRelateStatusEnum;
import vip.xiaonuo.vein.modular.veinpalmdeviceuserrelate.service.VeinPalmDeviceUserRelateService;
import vip.xiaonuo.vein.websocket.WebSocket;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 主动推送数据至掌静脉设备
 */
@Component
public class PushDataToPalmVeinDeviceTimerTask implements TimerTaskRunner {

    @Resource
    private WebSocket webSocket;

    @Autowired
    private VeinDeviceEventService veinDeviceEventService;

    @Resource
    private DeviceBaseService deviceBaseService;

    @Resource
    private VeinPalmDeviceUserRelateService relateService;

    @Resource
    private MemberUserService userService;

    @Resource
    private MemberFeaturesService featuresService;

    @Autowired
    private ReqUtil reqUtil;


    private List<DeviceBase> devices = new ArrayList<>();

    private List<String> tasks = new ArrayList<>();

    @Override
    public void action(String jobParams,String taskId) {
        if(tasks.contains(taskId)){
            return;
        }
        try{
            tasks.add(jobParams);
            DeviceBase device = deviceBaseService.getById(jobParams);
            if(device!=null && StringUtils.equals("1",device.getDeviceState())
                    && StringUtils.equals(DeviceCategory.SUB_TYPE_PALM+"",device.getDeviceType())){
                concatWithPalmVeinDevice(device);
            }
        }finally {
            tasks.remove(jobParams);
        }
    }

    @Override
    public void executeXxlJob() throws InterruptedException {
        concatWithPalmVeinDevice();
    }

    private void concatWithPalmVeinDevice() {
        devices = deviceBaseService.list(new LambdaQueryWrapper<DeviceBase>()
            .eq(DeviceBase :: getDeviceType , DeviceCategory.SUB_TYPE_PALM+"")
            .eq(DeviceBase :: getDeviceState , 1));

        for(DeviceBase device : devices){
            this.concatWithPalmVeinDevice(device);
        }
    }

    private void concatWithPalmVeinDevice(DeviceBase device) {
        String deviceNo = device.getRegistrationCode();
        LambdaQueryWrapper<VeinPalmDeviceUserRelate> wrapper = new LambdaQueryWrapper<VeinPalmDeviceUserRelate>()
                .eq(VeinPalmDeviceUserRelate :: getDeviceId , device.getId());

        wrapper.and((subWrapper)->{
            subWrapper.eq(VeinPalmDeviceUserRelate :: getStatus , VeinPalmDeviceRelateStatusEnum.ADD.getCode())
                    .or()
                    .eq(VeinPalmDeviceUserRelate :: getStatus , VeinPalmDeviceRelateStatusEnum.UPDATE.getCode());
        });

        List<VeinPalmDeviceUserRelate> relates = relateService.list(wrapper);
        try{
            for(int i = 0 ; i < relates.size() && i < 20 ; i++){
                VeinPalmDeviceUserRelate relate = relates.get(i);
                MemberUser user = userService.getById(relate.getUserId());
                if(user == null ){
                    if(relate.getStatus() == VeinPalmDeviceRelateStatusEnum.ADD.getCode()){ // 添加
                        relate.setStatus(VeinPalmDeviceRelateStatusEnum.ADD_FAIL.getCode());
                    }else if(relate.getStatus() == VeinPalmDeviceRelateStatusEnum.UPDATE.getCode()){ // 编辑
                        relate.setStatus(VeinPalmDeviceRelateStatusEnum.UPDATE_FAIL.getCode());
                    }
                    relate.setResult("用户id:"+relate.getUserId()+" ,对应的用户不存在");
                    continue;
                }

                MemberFeatures feature = featuresService.getOne(new LambdaQueryWrapper<MemberFeatures>()
                        .eq(MemberFeatures :: getDwMemberUserId , user.getId())
                        .eq(MemberFeatures :: getPlatform , DeviceCategory.SUB_TYPE_PALM));

                if(feature == null){
                    if(relate.getStatus() == VeinPalmDeviceRelateStatusEnum.ADD.getCode()){ // 添加
                        relate.setStatus(VeinPalmDeviceRelateStatusEnum.ADD_FAIL.getCode());
                    }else if(relate.getStatus() == VeinPalmDeviceRelateStatusEnum.UPDATE.getCode()){ // 编辑
                        relate.setStatus(VeinPalmDeviceRelateStatusEnum.UPDATE_FAIL.getCode());
                    }
                    relate.setResult("用户:"+user.getName()+" ,尚未录入掌静脉");
                    continue;
                }
                String serialNo = "";
                String data = "";
                if(relate.getStatus() == VeinPalmDeviceRelateStatusEnum.ADD.getCode()){ // 添加
                    AddFeatureInfo addFeatureInfo = new AddFeatureInfo(feature);
                    if(addFeatureInfo == null || addFeatureInfo.getAddFeatureInfo()==null || addFeatureInfo.getAddFeatureInfo().size()==0){
                        relate.setStatus(VeinPalmDeviceRelateStatusEnum.ADD_FAIL.getCode());
                        relate.setResult("用户:"+user.getName()+"，掌静脉数据异常:"+feature.getId());
                        continue;
                    }
                    serialNo = reqUtil.getReqSeriNo(deviceNo,addFeatureInfo);
                    data = serialNo.concat(JSON.toJSONString(addFeatureInfo));

                }else if(relate.getStatus() == VeinPalmDeviceRelateStatusEnum.UPDATE.getCode()){ // 编辑
                    UpdateFeatureInfo updateFeatureInfo = new UpdateFeatureInfo(feature);
                    if(updateFeatureInfo == null || updateFeatureInfo.getUpdateFeatureInfo()==null || updateFeatureInfo.getUpdateFeatureInfo().size()==0){
                        relate.setStatus(VeinPalmDeviceRelateStatusEnum.UPDATE_FAIL.getCode());
                        relate.setResult("用户:"+user.getName()+"，掌静脉数据异常:"+feature.getId());
                        continue;
                    }
                    serialNo = reqUtil.getReqSeriNo(deviceNo,updateFeatureInfo);
                    data = serialNo.concat(JSON.toJSONString(updateFeatureInfo));
                }

                VeinDeviceEvent veinDeviceEvent = new VeinDeviceEvent()
                        .setBody(user.getId()+"")
                        .setRequest(data)
                        .setStatus(VeinDeviceEventStatusEnum.EXECUTE.getCode())
                        .setSerialNumber(serialNo)
                        .setDeviceId(relate.getDeviceId());
                veinDeviceEvent.setSysType(VeinDeviceEventSysTypeEnum.MEMBER.getCode());
                veinDeviceEvent.setType(VeinDeviceEventPersonTypeEnum.FEATURE_ISSUED.getCode());

                relate.setSn(serialNo.substring(4));

                veinDeviceEventService.save(veinDeviceEvent);
                webSocket.sendOneMessage(deviceNo, data);
            }
        }finally {
            relateService.saveOrUpdateBatch(relates);
        }
    }
}
